package com.tbit.main.controller;

import cn.hutool.core.collection.CollUtil;
import com.tbit.common.constant.MethodEnum;
import com.tbit.common.constant.ModuleEnum;
import com.tbit.common.utils.TraceUtil;
import com.tbit.main.common.JsonResult;
import com.tbit.main.constant.OperateLog;
import com.tbit.main.constant.*;
import com.tbit.main.exception.BaseException;
import com.tbit.main.h2.pojo.ParkPoint;
import com.tbit.main.pojo.*;
import com.tbit.main.service.*;
import com.tbit.main.util.Assert;
import com.tbit.main.util.DateTimeUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 站点设备绑定表
 *
 * @author LMY
 * @create 2021-12-22 14:58
 */
@RestController
@RequestMapping("/parkPointBound")
public class ParkPointBoundController {

    @Autowired
    private TokenService tokenService;
    @Autowired
    private GeoreGionService georeGionService;
    @Autowired
    private ParkPointService parkPointService;
    @Autowired
    private ParkPointBoundService parkPointBoundService;
    @Autowired
    private ParkPointBoundAbnormalService parkPointBoundAbnormalService;
    @Autowired
    private CalibrateService calibrateService;


    /**
     * 根据区域查询
     *
     * @param token
     * @param accountId
     * @param mapType
     * @param type
     * @param regionId
     * @return
     */
    @RequestMapping("/getAccountId")
    public JsonResult getByAccountId(String token, Integer accountId, Integer mapType, Integer type,
                                     @RequestParam(value = "regionId", required = false) List<Integer> regionId) {
        Assert.notNull(accountId, "AccountUser.agentId.notNull");
        AccountUser accountUserToken = tokenService.getAccount(token);

        if (mapType == null) {
            mapType = SysConstant.GOOGLE;
        }

        if (CollUtil.isEmpty(regionId)) {
            regionId = georeGionService.getByAccountUserId(accountUserToken.getAccountUserId());
        }

        List<ParkPoint> parkPoints = new LinkedList<>();
        if (CollUtil.isNotEmpty(regionId)) {
            parkPoints = parkPointService.getByRegionId(regionId);
        } else {
            parkPoints = parkPointService.getByAccountId(accountId);
        }

        List<ParkPointBoundCount> parkPointBounds = new LinkedList<>();
        if (parkPoints.size() > 0) {
            parkPointBounds = parkPointBoundService.getByAccountId(parkPoints.stream().map(ParkPoint::getParkPointId).collect(Collectors.toList()), type);
        }

        Map<Integer, Map<Integer, Integer>> map = new HashMap<>();
        for (ParkPointBoundCount parkPointBoundCount : parkPointBounds) {
            if (map.containsKey(parkPointBoundCount.getParkPointId())) {
                map.get(parkPointBoundCount.getParkPointId()).put(parkPointBoundCount.getType(), parkPointBoundCount.getTotal());
            } else {
                Map<Integer, Integer> integerMap = new HashMap<>();
                integerMap.put(parkPointBoundCount.getType(), parkPointBoundCount.getTotal());
                map.put(parkPointBoundCount.getParkPointId(), integerMap);
            }
        }

        for (ParkPoint parkPoint : parkPoints) {
            if (map.containsKey(parkPoint.getParkPointId())) {
                List<ParkPointDeviceCount> parkPointDeviceCounts = new LinkedList<>();
                for (Integer map1 : map.get(parkPoint.getParkPointId()).keySet()) {
                    ParkPointDeviceCount parkPointDeviceCount = new ParkPointDeviceCount();
                    parkPointDeviceCount.setType(map1);
                    parkPointDeviceCount.setTotal(map.get(parkPoint.getParkPointId()).get(map1));
                    parkPointDeviceCounts.add(parkPointDeviceCount);
                }
                parkPoint.setParkPointDeviceCount(parkPointDeviceCounts);
            }
        }
        /** 校准 */
        calibrateService.celibrateParkPoint(parkPoints, mapType);
        return JsonResult.succ(parkPoints);
    }

    /**
     * 根据站点查询
     *
     * @param token
     * @param parkPointId
     * @param type
     * @return
     */
    @RequestMapping("/getByParkPointId")
    public JsonResult getByParkPointId(String token, Integer parkPointId, Integer type) {

        List<ParkPointBound> parkPointBounds = parkPointBoundService.getByParkPointId(parkPointId, type);

        return JsonResult.succ(parkPointBounds);
    }

    /**
     * 更新设备时间
     *
     * @param token
     * @param parameter
     * @return
     */
    @RequestMapping("/updateTime")
    public JsonResult updateTime(String token, Parameter parameter, Integer type) {
        Assert.notNull(type, "Machine.type.notNull");
        parkPointBoundService.updateTime(parameter.getMachineNOs(), type);
        return JsonResult.succ();
    }

    /**
     * 添加设备
     *
     * @param token
     * @param parkPointBound
     * @return
     */
    @RequestMapping("/add")
    @OperateLog(module = ModuleEnum.PARKPOINTBOUND, methods = MethodEnum.PARKPOINTBOUND_ADD)
    public JsonResult add(String token, ParkPointBound parkPointBound) {
        Assert.notNull(parkPointBound.getParkPointId(), "ParkPoint.id.notNull");
        Assert.notNull(parkPointBound.getMachineNO(), "Machine.machineNO.notNull");
        Assert.notNull(parkPointBound.getType(), "Machine.type.notNull");

        ParkPointBound parkPointBoundDB = parkPointBoundService.getByNO(parkPointBound.getMachineNO(), parkPointBound.getType());

        if (parkPointBoundDB != null) {
            return JsonResult.fail(500, "该设备已绑定站点", TraceUtil.getTraceIdByLocal());
        }

        parkPointBound.setAddTime(DateTimeUtil.getNowTime());
        parkPointBoundService.add(parkPointBound);
        return JsonResult.succ();
    }

    /**
     * 修改设备
     *
     * @param token
     * @return
     */
    @RequestMapping("/abnormal")
    @OperateLog(module = ModuleEnum.PARKPOINTBOUND, methods = MethodEnum.PARKPOINTBOUND_ABNORMAL)
    public JsonResult abnormal(String token, String machineNO, Integer type, Integer state) {

        Assert.notNull(machineNO, "Machine.machineNO.notNull");
        Assert.notNull(type, "Machine.type.notNull");

        ParkPointBound parkPointBound = parkPointBoundService.getByNO(machineNO, type);
        if (parkPointBound == null) {
            throw new BaseException("machienNO.is.notNull");
        }

        if (state != null) {
            /**修改异常状态*/
            parkPointBoundService.update(machineNO, type, state, null);
            if (state.equals(ParkPointBoundConstant.state_normal)) {
                /**删除异常*/
                parkPointBoundAbnormalService.del(machineNO);
            } else {
                /**添加异常*/
                ParkPointBound parkPointBoundDb = parkPointBoundService.getByNO(machineNO, type);
                ParkPoint parkPoint = parkPointService.getByParkPointId(parkPointBoundDb.getParkPointId());
                AccountUser accountUserToken = tokenService.getAccount(token);
                ParkPointBoundAbnormal parkPointBoundAbnormal = new ParkPointBoundAbnormal();
                parkPointBoundAbnormal.setMachineNO(machineNO);
                parkPointBoundAbnormal.setState(state);
                parkPointBoundAbnormal.setType(type);
                parkPointBoundAbnormal.setAddTime(DateTimeUtil.getNowTime());
                parkPointBoundAbnormal.setUserMainId(accountUserToken.getAccountUserId());
                parkPointBoundAbnormal.setAccountId(parkPoint.getAccountId());
                parkPointBoundAbnormalService.add(parkPointBoundAbnormal);
            }
        } else {
            /**删除绑定*/
            parkPointBoundService.del(machineNO);
            parkPointBoundAbnormalService.del(machineNO);
        }
        return JsonResult.succ();
    }

    /**
     * 修改设备备注
     *
     * @param token
     * @return
     */
    @RequestMapping("/update")
    @OperateLog(module = ModuleEnum.PARKPOINTBOUND, methods = MethodEnum.PARKPOINTBOUND_REMARK)
    public JsonResult update(String token, String machineNO, Integer type, String remark) {

        Assert.notNull(machineNO, "Machine.machineNO.notNull");
        Assert.notNull(type, "Machine.type.notNull");

        ParkPointBound parkPointBoundDb = parkPointBoundService.getByNO(machineNO, type);
        if (parkPointBoundDb == null) {
            throw new BaseException("machienNO.is.notNull");
        }

        /**修改异常状态*/
        parkPointBoundService.update(machineNO, type, null, remark);
        return JsonResult.succ();
    }

    /**
     * 查询单个
     *
     * @param token
     * @param machineNO
     * @return
     */
    @RequestMapping("/getByNO")
    public JsonResult getByNO(String token, String machineNO, Integer type) {
        Assert.notNull(type, "Machine.type.notNull");
        ParkPointBound parkPointBound = parkPointBoundService.getByNO(machineNO, type);
        return JsonResult.succ(parkPointBound);
    }

    /**
     * 批量新增
     *
     * @param machineNOs
     * @param parkPointId
     * @param type
     * @return
     */
    @RequestMapping("/addBatch")
    @OperateLog(module = ModuleEnum.PARKPOINTBOUND, methods = MethodEnum.PARKPOINTBOUND_ADD)
    public JsonResult addBatch(String machineNOs, Integer parkPointId, Integer type) {
        Assert.notNull(parkPointId, "ParkPoint.id.notNull");
        Assert.notNull(machineNOs, "Machine.machineNO.notNull");
        Assert.notNull(type, "Machine.type.notNull");
        parkPointBoundService.addBatch(machineNOs, parkPointId, type);
        return JsonResult.succ();
    }

    /**
     * 批量删除
     *
     * @param machineNOs
     * @param type
     * @return
     */
    @RequestMapping("/delBatch")
    @OperateLog(module = ModuleEnum.PARKPOINTBOUND, methods = MethodEnum.PARKPOINTBOUND_DEL)
    public JsonResult delBatch(String machineNOs, Integer type) {
        Assert.notNull(machineNOs, "Machine.machineNO.notNull");
        Assert.notNull(type, "Machine.type.notNull");
        parkPointBoundService.delBatch(Arrays.asList(machineNOs.split(",")), type);
        return JsonResult.succ();
    }
}
